home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / graph_alg / _mc_matching.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  9.9 KB  |  464 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _mc_matching.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. /*******************************************************************************
  16. *
  17. *  MAX_CARD_MATCHING  (maximum cardinality matching)
  18. *
  19. *  An implementation of Edmonds' algorithm 
  20. *
  21. *
  22. *  J. Edmonds:  Paths, trees, and flowers 
  23. *               Canad. J. Math., Vol. 17, 1965, 449-467
  24. *
  25. *  R.E. Tarjan: Data Structures and Network Algorithms,
  26. *               CBMS-NFS Regional Conference Series in Applied Mathematics,
  27. *               Vol. 44, 1983
  28. *
  29. *
  30. *  running time: O(n*m*alpha(n))
  31. *
  32. *
  33. *  S. Naeher (October 1991)
  34. *
  35. *******************************************************************************/
  36.  
  37.  
  38. #include <LEDA/graph_alg.h>
  39. #include <LEDA/node_partition.h>
  40.  
  41.  
  42. enum LABEL {ODD, EVEN, UNREACHED};
  43.  
  44. static int cmp_degree(const node& v,const node& w)  // compare indeg of v and w
  45. { return indeg(v) - indeg(w); }
  46.  
  47.  
  48. static int greedy( graph &G, node_data<node>& mate )   // greedy heuristic
  49. { node v;
  50.   int count = 0;
  51.   forall_nodes(v,G)
  52.     if (mate[v] == nil)
  53.     { edge e;
  54.       forall_adj_edges(e,v)
  55.       { node w = target(e);
  56.         if (v != w && mate[w] == nil) 
  57.         { mate[v] = w;
  58.           mate[w] = v;
  59.           count++;
  60.           break;
  61.          }
  62.        }
  63.      }
  64.    return count;
  65.  }
  66.  
  67.  
  68.  
  69. static void heuristic( graph &G, node_data<node>& mate )
  70. {
  71.  // Heuristic (Markus Paul):
  72.  // finds almost all augmenting paths of length <=3 with two passes over
  73.  // the adjacency lists
  74.  // ("almost": discovery of a blossom {v,w,x,v} leads to a skip of the
  75.  // edge (x,v), even if the base v stays unmatched - it's not worth while
  76.  // to fix this problem)
  77.  // if all adjacent nodes w of v are matched, try to find an other 
  78.  // partner for mate[x], and match v and w on success
  79.  
  80.   node u,v;
  81.   bool found;
  82.   node_data<int> all_matched(G,false);
  83.  
  84.   forall_nodes( v, G )
  85.   {
  86.     edge e = G.first_adj_edge(v);
  87.  
  88.     if( mate[v]==nil )
  89.     {
  90.         while(e != nil && mate[target(e)]!=nil) e = G.adj_succ(e);
  91.  
  92.         if( e != nil ) 
  93.           { mate[v] = target(e);  
  94.             mate[target(e)] = v ;  
  95.            }
  96.         else // second pass
  97.           {
  98.         all_matched[v] = true;
  99.  
  100.             forall_adj_edges(e,v)
  101.             {
  102.               node w = target(e);
  103.               node x = mate[w];
  104.     
  105.               if( ! all_matched[x] ) 
  106.               {
  107.                 while((found=G.next_adj_node(u,x)) && (u==v || mate[u]!=nil));
  108.     
  109.                 if( found ) 
  110.                   { mate[u] = x;  mate[x] = u ;
  111.                     mate[v] = w;  mate[w] = v ;
  112.                     G.init_adj_iterator(x);
  113.                     break;
  114.                    }
  115.             else
  116.                    all_matched[x] = true;
  117.                }
  118.              }
  119.            }
  120.         } 
  121.     }
  122.  
  123. }
  124.  
  125.  
  126.  
  127.  
  128. static void find_path(list<node>& L, node_array<int>&  label,
  129.                                      node_array<node>& pred,
  130.                                      node_data<node>& mate,
  131.                                      node_array<edge>& bridge,
  132.                                      node x, node y)
  133. {
  134.   /* computes an even length alternating path from x to y begining with a 
  135.      matching edge (Tarjan: Data Structures and Network Algorithms, page 122)
  136.      Preconditions: 
  137.      a) x and y are even or shrinked
  138.      b) when x was made part of a blossom for the first time, y was a base 
  139.         and predecessor of the base of that blossom
  140.    */
  141.  
  142.  if (x==y) 
  143.  { // [ x ]
  144.    L.append(x);
  145.    return;
  146.   }
  147.  
  148.  if (label[x] == EVEN) 
  149.  { // [ x --> mate[x] --> path(pred[mate[x]],y) ]
  150.    find_path(L,label,pred,mate,bridge,pred[mate[x]],y);
  151.    L.push(mate[x]);
  152.    L.push(x);
  153.    return;
  154.  }
  155.  
  156.  if (label[x] == ODD) 
  157.  { // [ x --> REV(path(source(bridge),mate[x])) --> path(target(bridge),y)) ]
  158.    node v;
  159.    list<node> L1;
  160.    find_path(L,label,pred,mate,bridge,target(bridge[x]),y);
  161.    find_path(L1,label,pred,mate,bridge,source(bridge[x]),mate[x]);
  162.    forall(v,L1) L.push(v);
  163.    L.push(x);
  164.    return;
  165.   }
  166. }
  167.  
  168.  
  169.  
  170.  
  171. list<edge> MAX_CARD_MATCHING(graph& G, int heur)
  172.  
  173.  
  174.   // input: directed graph G, we make it undirected (symmetric) by inserting
  175.   //        reversal edges
  176.  
  177.  
  178.   list<edge> R;
  179.  
  180.   int    strue = 0;
  181.   bool   done  = false;
  182.  
  183.   node_array<int>  label(G,UNREACHED);
  184.   node_array<node> pred(G,nil);
  185.   node_array<int>  path1(G,0);
  186.   node_array<int>  path2(G,0);
  187.   node_array<edge> bridge(G,nil);
  188.  
  189.   node_data<node> mate(G,nil);
  190.  
  191.  
  192.   // make graph symmetric
  193.  
  194.   edge_array<edge> rev(G,nil);
  195.   compute_correspondence(G,rev);
  196.  
  197.   edge e = G.first_edge();
  198.  
  199.   while (e && rev[e]) e = G.succ_edge(e);
  200.  
  201.   edge last_edge = nil;
  202.   if (e !=nil)
  203.   { last_edge = G.new_edge(target(e),source(e));
  204.     R.append(last_edge);
  205.     while (e != last_edge)
  206.     { if (rev[e] == nil)
  207.       { edge e1 = G.new_edge(target(e),source(e));
  208.         rev[e] = e1;
  209.         R.append(e1);
  210.         }
  211.       e = G.succ_edge(e);
  212.      }
  213.    }
  214.  
  215.   edge_array<edge> reversal(G,nil);
  216.  
  217.   for(e = G.first_edge(); e != last_edge; e = G.succ_edge(e))
  218.   { edge r = rev[e];
  219.     reversal[e] = r;
  220.     reversal[r] = e;
  221.    }
  222.  
  223.  
  224. /*
  225.   edge_array<edge> reversal(G,nil);
  226.  
  227.   edge e = G.first_edge();
  228.   edge last_edge = G.last_edge();
  229.  
  230.   do { edge e1 = G.new_edge(target(e),source(e));
  231.        reversal[e] = e1;
  232.        reversal[e1] = e;
  233.        R.append(e1);
  234.        e = G.succ_edge(e);
  235.       }
  236.   while(e != last_edge);
  237. */
  238.  
  239.  
  240.  
  241.   switch (heur) {
  242.  
  243.   case 1: { greedy(G,mate);
  244.             break;
  245.           }
  246.  
  247.   case 2: { G.sort_nodes(cmp_degree);  // sort nodes by degree
  248.             heuristic(G,mate);
  249.             break;
  250.            }
  251.   }
  252.  
  253.  
  254.   while (! done)  /* main loop */
  255.   {
  256.     node_list Q;
  257.     node v;
  258.  
  259.     node_partition base(G);    // now base(v) = v for all nodes v
  260.  
  261.     done = true;
  262.    
  263.     forall_nodes(v,G)
  264.     { pred[v] = nil;
  265.   
  266.       if (mate[v] == nil)
  267.       { label[v] = EVEN; 
  268.         Q.append(v); 
  269.        }
  270.       else label[v] = UNREACHED;
  271.     }
  272.   
  273.     while (!Q.empty())    // search for augmenting path
  274.     {
  275.       node v = Q.pop();
  276.       edge e;
  277.  
  278.       forall_adj_edges(e,v)
  279.       {
  280.         node w = G.target(e);
  281.  
  282.         if (v == w) continue;    // ignore self-loops
  283.  
  284.         if (base(v) == base(w) || (label[w] == ODD && base(w) == w)) 
  285.         continue;   // do nothing
  286.  
  287.         if (label[w] == UNREACHED)
  288.         { label[w] = ODD;
  289.           pred[w] = v;
  290.           label[mate[w]] = EVEN;
  291.           Q.append(mate[w]);
  292.          }
  293.         else  // base(v) != base(w) && (label[w] == EVEN || base(w) !=w)
  294.         { 
  295.           node hv = base(v);
  296.           node hw = base(w);
  297.   
  298.           strue++;
  299.           path1[hv] = path2[hw] = strue;
  300.   
  301.           while ((path1[hw] != strue && path2[hv] != strue) &&
  302.                  (mate[hv] != nil || mate[hw] != nil) )
  303.           {
  304.             if (mate[hv] != nil)
  305.             { hv = base(pred[mate[hv]]);
  306.               path1[hv] = strue;
  307.              }
  308.   
  309.             if (mate[hw] != nil)
  310.             { hw = base(pred[mate[hw]]);
  311.               path2[hw] = strue;
  312.              }
  313.            }
  314.   
  315.           if (path1[hw] == strue || path2[hv] == strue)  // Shrink Blossom
  316.           { node x;
  317.             node y;
  318.             node b = (path1[hw] == strue) ? hw : hv;    // Base
  319.  
  320. #if defined(REPORT_BLOSSOMS)
  321.   cout << "SHRINK BLOSSOM\n";
  322.   cout << "bridge = "; 
  323.   G.print_edge(e);
  324.   newline;
  325.   cout << "base   = "; 
  326.   G.print_node(b);
  327.   newline;
  328.   cout << "path1  = ";
  329. #endif
  330.  
  331.             x = base(v);
  332.             while (x != b)
  333.             { 
  334.  
  335. #if defined(REPORT_BLOSSOMS)
  336.   G.print_node(x); 
  337.   cout << " ";
  338. #endif
  339.               base.union_blocks(x,b);
  340.               base.make_rep(b);
  341.  
  342.               x = mate[x];
  343.  
  344. #if defined(REPORT_BLOSSOMS)
  345.   G.print_node(x); 
  346.   cout << " ";
  347. #endif
  348.               y = base(pred[x]);
  349.               base.union_blocks(x,b);
  350.               base.make_rep(b);
  351.  
  352.               Q.append(x);
  353.  
  354.               bridge[x] = e;
  355.               x = y;
  356.              }
  357.  
  358. #if defined(REPORT_BLOSSOMS)
  359.   G.print_node(b);
  360.   newline;
  361.   cout << "path2  = ";
  362. #endif
  363.  
  364.             x = base(w);
  365.             while (x != b)
  366.             { 
  367.  
  368. #if defined(REPORT_BLOSSOMS)
  369.   G.print_node(x); 
  370.   cout << " ";
  371. #endif
  372.               base.union_blocks(x,b);
  373.               base.make_rep(b);
  374.  
  375.               x = mate[x];
  376.  
  377. #if defined(REPORT_BLOSSOMS)
  378.   G.print_node(x); 
  379.   cout << " ";
  380. #endif
  381.               y = base(pred[x]);
  382.  
  383.               base.union_blocks(x,b);
  384.               base.make_rep(b);
  385.  
  386.               Q.append(x);
  387.  
  388.               bridge[x] = reversal[e];
  389.  
  390.               x = y;
  391.              }
  392.  
  393. #if defined(REPORT_BLOSSOMS)
  394.   G.print_node(b);
  395.   newline;
  396.   newline;
  397. #endif
  398.           }
  399.           else  // augment path
  400.           {
  401.             list<node> P[2];
  402.  
  403.             find_path(P[0],label,pred,mate,bridge,v,hv);
  404.             P[0].push(w);
  405.             find_path(P[1],label,pred,mate,bridge,w,hw);
  406.             P[1].pop();
  407.  
  408.             for(int i=0; i<2; i++)
  409.               while(! P[i].empty())
  410.                { node a = P[i].pop();
  411.                  node b = P[i].pop();
  412.                  mate[a] = b;
  413.                  mate[b] = a;
  414.                 }
  415.  
  416.              Q.clear();                /* stop search (while Q not empty) */
  417.              done = false;             /* continue main loop              */
  418.              G.init_adj_iterator(v);
  419.              break;                    /* forall_adj_edges(e,v) ...       */
  420.            }
  421.  
  422.         } // base(v) != base(w) && (label[w] == EVEN || base(w) !=w)
  423.   
  424.       } // for all adjacent edges
  425.   
  426.     } // while Q not empty
  427.  
  428.   } // while not done
  429.  
  430.  
  431.  forall(e,R) G.del_edge(e);  // restore graph (only original edges in result!)
  432.  
  433.  list<edge> result;
  434.  
  435. /*
  436.   node v;
  437.   forall_nodes(v,G)
  438.     if (mate[v] != nil)
  439.     { edge e;
  440.       forall_adj_edges(e,v)
  441.         if (mate[target(e)] == v) 
  442.         { result.append(e);
  443.           break;
  444.          }
  445.      }
  446. */
  447.  
  448.  forall_edges(e,G) 
  449.  { node v = source(e);
  450.    node w = target(e);
  451.    if ( v != w  &&  mate[v] == w ) 
  452.    { result.append(e);
  453.      mate[v] = v;
  454.      mate[w] = w;
  455.     }
  456.   }
  457.  
  458.  return result;
  459.  
  460. }
  461.  
  462.